package org.springblade.modules.app.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.OrderQueryModel;
import com.jpay.ext.kit.HttpKit;
import com.jpay.ext.kit.PaymentKit;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.config.WxPayConfig;
import org.springblade.common.constant.OrderConstant;
import org.springblade.common.utils.DecimalUtil;
import org.springblade.common.utils.JpushTemplate;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.modules.app.entity.*;
import org.springblade.modules.app.service.*;
import org.springblade.modules.netty.NettyHandler;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;


/**
 * @author kingk
 * 微信支付回调
 * 1.必须 要纳入白名单
 * 2.验签后  处理业务逻辑
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("blade-app/wxNotify")
public class WxPayNotifyController extends BladeController {

    private final ICoalService coalService;
    private final IUserService userService;
    private final IMoneyDetailService moneyDetailService;
    private final ICouponsService couponsService;
    private final IOrderPoundageService orderPoundageService;

    private final IJpushService jpushService;

    /////支付回调
    @PostMapping("/payOrderNotify")
    public synchronized String payOrderNotify(HttpServletRequest request) {
        String notifyXmlMsg = HttpKit.readData(request);
        log.info("商户支付返回报文:" + notifyXmlMsg);
        Map<String, String> notifyResult = WxPayKit.xmlToMap(notifyXmlMsg);
        Boolean verifyFlag = WxPayKit.verifyNotify(notifyResult, WxPayConfig.partnerKey, SignType.HMACSHA256);
        if (verifyFlag.equals(false)) {
            log.info("签名失败");
        }
        String returnCode = notifyResult.get("return_code");
        String returnMsg = notifyResult.get("return_msg");
        log.info("报文信息returnMsg:" + returnMsg);
        String result_code = notifyResult.get("result_code");
        if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(result_code)) {
            String transactionId = notifyResult.get("transaction_id");
            String prepayId = notifyResult.get("prepay_id");
            String orderId = notifyResult.get("out_trade_no");
            //查询订单信息
            LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.and(wrapper -> wrapper.eq(Order::getTopayid, prepayId));
            queryWrapper.and(wrapper -> wrapper.eq(Order::getMerchno, orderId));
            Order orderInfo = coalService.getOne(queryWrapper);

            User workerUserInfo = userService.getById(orderInfo.getWorkerid());
            User merchantUserInfo = userService.getById(orderInfo.getCuserid());

            orderInfo.setTradeno(transactionId);
            orderInfo.setPaytime(new Date());
/////////////////////////////////商户付款通知///////////////////////////////////////////
            //订单状态为3  违约状态为1 说明是商户支付订单
            if (OrderConstant.ORDER_STATUS_3.equals(orderInfo.getOrderstatus()) && "1".equals(orderInfo.getQxstatus())) {
                orderInfo.setOrderstatus("4");
                coalService.updateById(orderInfo);
                ///扣点值
                List<OrderPoundage> list = orderPoundageService.list();
                //工人应收金额 下单价*(1-n%) n为扣率
                BigDecimal workerReceiveMoney = DecimalUtil.workderRealMoneyRegular(orderInfo.getOrderprice(), list.get(0).getPoundage());
                //工人新账户余额
                BigDecimal workderNewAccountMoney = DecimalUtil.add(workerUserInfo.getAccountmoney(), workerReceiveMoney);
                //记录明细
                MoneyDetail moneyDetail = new MoneyDetail();
                moneyDetail.setId(IdWorker.getId());
                moneyDetail.setUserid(orderInfo.getCuserid() + "");
                moneyDetail.setOrderid(orderInfo.getId() + "");
                moneyDetail.setFkfserid(orderInfo.getCuserid());
                moneyDetail.setFkfname(orderInfo.getCusername());
                moneyDetail.setFkfphone(orderInfo.getCuserphone());
                moneyDetail.setTrademoney(workerReceiveMoney);
                moneyDetail.setMoneymark("商户订单支付:[商户支付金额]" + orderInfo.getPayamount() + "[平台优惠券金额]:" + orderInfo.getDiscountprice());
                moneyDetail.setSkfuserid(orderInfo.getWorkerid());
                moneyDetail.setSkfusername(orderInfo.getWorkername());
                moneyDetail.setSkfuserphone(orderInfo.getWorkerphone());
                moneyDetail.setBefmoeny(workerUserInfo.getAccountmoney());
                moneyDetail.setAftmoney(workderNewAccountMoney);
                moneyDetail.setMoneytype("1");
                moneyDetail.setCtime(new Date());
                moneyDetailService.save(moneyDetail);
                ////更新 工人新账户余额
                workerUserInfo.setAccountmoney(workderNewAccountMoney);
                userService.updateById(workerUserInfo);
                ////去作废已用的优惠券
                if (!StringUtils.isEmpty(orderInfo.getDiscountid())) {
                    Coupons coupons = new Coupons();
                    coupons.setId(Long.valueOf(orderInfo.getDiscountid()));
                    coupons.setDelflag(2);
                    couponsService.updateById(coupons);
                }
                Map<String, String> xml = new HashMap<String, String>();
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                return PaymentKit.toXml(xml);
            } else if ("2".equals(orderInfo.getQxstatus())) {
                orderInfo.setQxstatus("3");
                coalService.updateById(orderInfo);
                Map<String, String> xml = new HashMap<String, String>();
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                return PaymentKit.toXml(xml);
            }
            Map<String, String> xml = new HashMap<String, String>();
            xml.put("return_code", "SUCCESS");
            xml.put("return_msg", "OK");
            return PaymentKit.toXml(xml);
        } else {
            Map<String, String> xml = new HashMap<String, String>();
            xml.put("return_code", "FAIL");
            xml.put("return_msg", "订单信息异常" + returnMsg);
            log.error("订单信息异常" + returnMsg);
            return PaymentKit.toXml(xml);
        }
    }


    @PostMapping("/appOrderNotify/{orderId}")
    public synchronized R appOrderNotify(@PathVariable("orderId") Long orderId) {
        Order orderInfo = coalService.getById(orderId);
        Map<String, String> params = OrderQueryModel.builder()
                .nonce_str(IdWorker.getIdStr())
                .mch_id(WxPayConfig.mchId)
                .appid(WxPayConfig.appId)
                .out_trade_no(orderInfo.getId() + "")
                .build()
                .createSign(WxPayConfig.partnerKey, SignType.MD5, false);
        String orderQuery = WxPayApi.orderQuery(params);
        Map<String, String> result = WxPayKit.xmlToMap(orderQuery);
        log.info("===" + result);
        String returnCode = result.get("return_code");
        String resultCode = result.get("result_code");
        String transaction_id = result.get("transaction_id");
        String trade_state = result.get("trade_state");

        if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) {

            if (WxPayKit.codeIsOk(trade_state)) {
                if (OrderConstant.ORDER_STATUS_4.equals(orderInfo.getOrderstatus()) && "1".equals(orderInfo.getQxstatus())) {
                    log.info("正常 不在处理");
                }

                if ("3".equals(orderInfo.getQxstatus())) {
                    log.info("正常 不在处理");
                }

                User workerUserInfo = userService.getById(orderInfo.getWorkerid());

                if (OrderConstant.ORDER_STATUS_3.equals(orderInfo.getOrderstatus()) && "1".equals(orderInfo.getQxstatus())) {

                    orderInfo.setTradeno(transaction_id);
                    orderInfo.setOrderstatus("4");
                    orderInfo.setPaytime(new Date());
                    coalService.updateById(orderInfo);
                    ///扣点值
                    List<OrderPoundage> orderPoundage = orderPoundageService.list();
                    //工人应收金额 下单价*(1-n%) n为扣率
                    BigDecimal workerReceiveMoney = DecimalUtil.workderRealMoneyRegular(orderInfo.getOrderprice(), orderPoundage.get(0).getPoundage());
                    //工人新账户余额
                    BigDecimal workderNewAccountMoney = DecimalUtil.add(workerUserInfo.getAccountmoney(), workerReceiveMoney);
                    //记录明细
                    MoneyDetail moneyDetail = new MoneyDetail();
                    moneyDetail.setId(IdWorker.getId());
                    moneyDetail.setUserid(orderInfo.getCuserid() + "");
                    moneyDetail.setOrderid(orderInfo.getId() + "");
                    moneyDetail.setFkfserid(orderInfo.getCuserid());
                    moneyDetail.setFkfname(orderInfo.getCusername());
                    moneyDetail.setFkfphone(orderInfo.getCuserphone());
                    moneyDetail.setTrademoney(workerReceiveMoney);
                    moneyDetail.setMoneymark("商户订单支付:[商户支付金额]" + orderInfo.getPayamount() + "[平台优惠券金额]:" + orderInfo.getDiscountprice() + "微信交易凭证" + WxPayKit.xmlToMap(orderQuery));
                    moneyDetail.setSkfuserid(orderInfo.getWorkerid());
                    moneyDetail.setSkfusername(orderInfo.getWorkername());
                    moneyDetail.setSkfuserphone(orderInfo.getWorkerphone());
                    moneyDetail.setBefmoeny(workerUserInfo.getAccountmoney());
                    moneyDetail.setAftmoney(workderNewAccountMoney);
                    moneyDetail.setMoneytype("1");
                    moneyDetail.setCtime(new Date());
                    moneyDetailService.save(moneyDetail);
                    ////更新 工人新账户余额
                    workerUserInfo.setAccountmoney(workderNewAccountMoney);
                    userService.updateById(workerUserInfo);
                    ////去作废已用的优惠券
                    if (!StringUtils.isEmpty(orderInfo.getDiscountid())) {
                        Coupons coupons = new Coupons();
                        coupons.setId(Long.valueOf(orderInfo.getDiscountid()));
                        coupons.setDelflag(2);
                        couponsService.updateById(coupons);
                    }
                    NettyHandler.handleOrderWorkerId(orderInfo.getWorkerid(), orderInfo.getCusername() + "商家已付款");
                    //FIXME  通知消息 极光
                    Jpush jpush = jpushService.getById(orderInfo.getWorkerid());
                    if (!StringUtils.isEmpty(jpush)) {
                        List<String> jgusers = new ArrayList<>();
                        jgusers.add(jpush.getRegistrationid());
                        JpushTemplate.pushMessage(jgusers, orderInfo.getCusername() + "商家已付款");
                    }
                } else if ("2".equals(orderInfo.getQxstatus())) {
                    orderInfo.setQxstatus("3");
                    coalService.updateById(orderInfo);
                }
            }
        } else {
            log.error("资金安全日志: 交易失败" + WxPayKit.xmlToMap(orderQuery));
        }
        return R.success("");
    }

    @ResponseBody
    @GetMapping("/payOrderResultQuery")
    public R payOrderResultQuery(Order order) {
        Map<String, String> params = OrderQueryModel.builder()
                .nonce_str(IdWorker.getIdStr())
                .mch_id(WxPayConfig.mchId)
                .appid(WxPayConfig.appId)
//                .transaction_id(order.getTradeno())
                .out_trade_no(order.getId() + "")
                .build()
                .createSign(WxPayConfig.partnerKey, SignType.MD5, false);
        String orderQuery = WxPayApi.orderQuery(params);
        Map<String, String> result = WxPayKit.xmlToMap(orderQuery);
        return R.data(result);
    }
}
